#ifndef __THREADPOOL__
#define __THREADPOOL__

#include <iostream>
#include <pthread.h>
#include <queue>
#include "Log.hpp"

int NUM = 5;


typedef int(*ProcessThings)(int);

class Task{
public:
    int sock;
    ProcessThings process;

    Task()
    {}
    
    void SetTask(int sock_, ProcessThings process_)
    {
        sock = sock_;
        process = process_;
    }

    void Run()
    {
        process(sock);
    }

    ~Task()
    {}
};//任务类


class ThreadPool
{
public:
    int total;//线程池中线程的总数
    int idlenum;//线程池中休眠的线程的总数
    std::queue<Task> taskqueue;//任务队列
    pthread_mutex_t mutex;
    pthread_cond_t cond;
    bool isexit;

    ThreadPool(int total_ = 5)
        :total(total_)
        ,isexit(false)
    {
        NUM = total_;     
    }

    static void* GetTask(void* this_)
    {
        pthread_detach(pthread_self());
        ThreadPool* tp = (ThreadPool*)this_;
        //访问公共资源taskqueue，在访问之前必须先获得锁
        tp->Lock();
        //从队列中读取任务
        while(1){
        while(tp->taskqueue.size() == 0)
            {
                if(tp->isexit)
                {
                    tp->total--;
                    tp->Unlock();
                    std::cout<<"begin to exit"<<std::endl;
                    pthread_exit(NULL);
                }
            ++(tp->idlenum);
            std::cout<<"begin to idle"<<std::endl;
            tp->Idle();
        }
        std::cout<<"wake up to do things"<<std::endl;
        Task task = tp->taskqueue.front();
        tp->taskqueue.pop();
        task.Run();
        tp->Unlock();
        }
    }

    void InitThreadPool()
    {
        for(int i = 0; i < NUM; ++i)
        {
            pthread_t tid;
            pthread_create(&tid, NULL, GetTask, this);
        }
    }

    void PushTask(Task& task)
    {
        taskqueue.push(task);
        WakeupOneThread();
    }

    void Idle()//线程休眠函数
    {
        pthread_cond_wait(&cond, &mutex);
    }
    
    void WakeupOneThread()//wakeup one thread
    {
        Lock();
        idlenum--;
            Unlock();
            pthread_cond_signal(&cond);
        }

        void Lock()//上锁
        {
            pthread_mutex_lock(&mutex);
        }

    void Unlock()//解锁
    {
        pthread_mutex_unlock(&mutex);
    }

    void Stop()
    {
        if(idlenum != 0)
        {
            pthread_cond_broadcast(&cond);
        }
        isexit = true;
    }

    ~ThreadPool()
    {}
    
};

#endif


